﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Noris.Tools.TraceVisualiser.BlockingVisualiser.Data;
using Noris.Tools.TraceVisualiser.Components;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace Noris.Tools.TraceVisualiser.BlockingVisualiser.Components
{
    #region class LockInfoRelation : popisuje vztah mezi procesem a zdrojem, a to jak věcně (vztahy na datové objekty) tak místně (vztahy na controly) a graficky (hostuje v sobě objekt Arrow)
    /// <summary>
    /// LockInfoRelation : popisuje vztah mezi procesem a zdrojem, 
    /// a to jak věcně (vztahy na datové objekty) 
    /// tak místně (vztahy na controly) a graficky (hostuje v sobě objekt Arrow).
    /// Účelem je podpora grafické reprezentace.
    /// </summary>
    internal class LockInfoRelation
    {
        internal bool IsOwner;
        internal RelationSpidResource RelationSpidResource;
        internal SqlSpidInfo SpidInfo { get { return RelationSpidResource.SpidInfo; } }
        internal SqlProcessInfo ProcessInfo;
        internal SqlResourceInfo ResourceInfo { get { return RelationSpidResource.ResourceInfo; } }
        internal LockInfoList SpidView;
        internal LockInfoList ProcessView;
        internal LockInfoList ResourceView;
        internal ArrowRelation VisualArrow;
        internal bool IsLinkedToSpid { get { return (this.SpidView != null && this.ResourceView != null); } }
        internal bool HasArrow { get { return (this.VisualArrow != null); } }
        /// <summary>
        /// Vrstva: IsOwner (true) = 0, (false) = 1
        /// </summary>
        internal int Layer { get { return (this.IsOwner ? 0 : 1); } }
        /// <summary>
        /// Komparátor podle vrstev, dovoluje vykerslit dospodu šipky Owner (tlustší) a navrch Waiter (tenčí)
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static int CompareByLayer(LockInfoRelation a, LockInfoRelation b)
        {
            if (a == null && b == null) return 0;
            if (a == null) return -1;
            if (b == null) return 1;
            return a.Layer.CompareTo(b.Layer);
        }
    }
    #endregion
    #region class ArrowRelation : potomek Arrow, rozšířený o barvy a texty
    internal class ArrowRelation : Arrow
    {
        public bool UseSlantBrush { get; set; }
        public Color Color1 { get; set; }
        public Color Color2 { get; set; }
        public Color ColorLine { get; set; }
        public Color ColorText { get; set; }
        public string Text { get; set; }
        public string ToolTipText { get; set; }
        
        /// <summary>
        /// Vykreslí šipku (ale ne text)
        /// </summary>
        /// <param name="graphics"></param>
        internal void DrawArrow(Graphics graphics)
        {
            if (this.UseSlantBrush)
            {
                using (Brush brush = this.GetBrushSlant(this.Color1, this.Color2))
                {
                    graphics.FillPath(brush, this.Path);
                }
            }
            else
            {
                using (Brush brush = this.GetBrushLength(this.Color1, this.Color2))
                {
                    graphics.FillPath(brush, this.Path);
                }
            }
            if (!this.ColorLine.IsEmpty)
            {
                using (Pen pen = new Pen(this.ColorLine, 1f))
                {
                    graphics.DrawPath(pen, this.Path);
                }
            }
        }
        /// <summary>
        /// Vykreslí text
        /// </summary>
        /// <param name="graphics"></param>
        /// <param name="font"></param>
        internal void DrawText(Graphics graphics, Font font)
        {
            string text = this.Text;
            if (String.IsNullOrEmpty(text)) return;

            // Najdu místo na šipce, kam nalepím text = na šipce, 25% od základny:
            VectorD vector = this.Vector;
            PointD home = vector.GetPointAtDistance(0.25d * VectorD.GetDistance(this.Begin, this.End)).Value;

            // Určím velikost textu:
            SizeF textSize = graphics.MeasureString(text, font);
            if (textSize.Width > 75f) textSize.Width = 75f;
            RoundEdgeRectangle textArea = new RoundEdgeRectangle(PointF.Empty, textSize, 3, 2);
            textArea.PointCenter = home;
            RectangleF textBounds = textArea.Bounds;           // Zapamatuji si prostor pro text
            textArea.Resize(4, 3);                             // Prostor zvětším o kousek od textu
            using (PathGradientBrush pgb = new PathGradientBrush(textArea.Path))
            {
                pgb.InterpolationColors = new ColorBlend(3)
                {
                    Positions = new float[] { 0.0f, 0.2f, 1.0f },
                    Colors = new Color[] { this.Color2, Color.LightYellow, Color.LightYellow }
                };
                graphics.FillPath(pgb, textArea.Path);
            }

            if (!this.ColorLine.IsEmpty)
            {
                using (Pen pen = new Pen(this.ColorLine, 1f))
                {
                    graphics.DrawPath(pen, textArea.Path);
                }
            }

            Color colorText = (this.ColorText.IsEmpty ? Color.Black : this.ColorText);
            using (SolidBrush textBrush = new SolidBrush(colorText))
            {
                textBounds.Width = textBounds.Width + 3;
                graphics.DrawString(text, font, textBrush, textBounds);
            }
        }
    }
    #endregion
}
